import { ref, computed, reactive, watch } from 'vue'
import { Scene } from '../scene/Scene'
import { Character } from '../character/Character'

/**
 * 时间轴轨道类型
 */
export enum TrackType {
  CHARACTER = 'character',
  AUDIO = 'audio',
  EFFECT = 'effect',
  CAMERA = 'camera'
}

/**
 * 时间轴轨道
 */
export interface Track {
  id: string
  name: string
  type: TrackType
  targetId?: string // 关联的角色或对象ID
  visible: boolean
  locked: boolean
  height: number
  color: string
}

/**
 * 时间轴标记
 */
export interface Marker {
  id: string
  frame: number
  name: string
  color: string
  description?: string
}

/**
 * 时间轴选区
 */
export interface Selection {
  startFrame: number
  endFrame: number
  tracks: string[] // 选中的轨道ID
}

/**
 * 时间轴配置
 */
export interface TimelineConfig {
  fps: number
  totalFrames: number
  pixelsPerFrame: number
  snapToFrames: boolean
  showGrid: boolean
  gridInterval: number
}

/**
 * 时间轴类
 */
export class Timeline {
  public readonly id: string
  public name = ref('')
  
  // 时间轴配置
  public config = reactive<TimelineConfig>({
    fps: 30,
    totalFrames: 300,
    pixelsPerFrame: 4,
    snapToFrames: true,
    showGrid: true,
    gridInterval: 10
  })
  
  // 当前播放头位置
  public playhead = ref(0)
  
  // 轨道列表
  public tracks = ref<Track[]>([])
  
  // 标记列表
  public markers = ref<Marker[]>([])
  
  // 当前选区
  public selection = ref<Selection | null>(null)
  
  // 缩放级别
  public zoom = ref(1)
  
  // 滚动位置
  public scrollX = ref(0)
  public scrollY = ref(0)
  
  // 关联的场景
  public scene = ref<Scene | null>(null)
  
  constructor(id: string, name: string = '') {
    this.id = id
    this.name.value = name || `Timeline_${id.slice(0, 8)}`
    
    // 监听播放头变化，更新场景
    watch(this.playhead, (newFrame) => {
      if (this.scene.value) {
        this.scene.value.updateToFrame(newFrame)
      }
    })
  }
  
  /**
   * 设置关联场景
   */
  public setScene(scene: Scene): void {
    this.scene.value = scene
    this.config.fps = scene.config.fps
    this.config.totalFrames = scene.config.duration
    
    // 为场景中的每个角色创建轨道
    this.syncTracksWithScene()
  }
  
  /**
   * 同步轨道与场景
   */
  public syncTracksWithScene(): void {
    if (!this.scene.value) return
    
    const existingCharacterTracks = this.tracks.value.filter(t => t.type === TrackType.CHARACTER)
    const sceneCharacters = this.scene.value.characters.value
    
    // 为新角色创建轨道
    sceneCharacters.forEach(character => {
      if (!existingCharacterTracks.find(t => t.targetId === character.id)) {
        this.addCharacterTrack(character)
      }
    })
    
    // 移除不存在的角色轨道
    existingCharacterTracks.forEach(track => {
      if (!sceneCharacters.find(c => c.id === track.targetId)) {
        this.removeTrack(track.id)
      }
    })
  }
  
  /**
   * 添加角色轨道
   */
  public addCharacterTrack(character: Character): Track {
    const track: Track = {
      id: `track_${character.id}`,
      name: character.name.value,
      type: TrackType.CHARACTER,
      targetId: character.id,
      visible: true,
      locked: false,
      height: 40,
      color: this.generateTrackColor()
    }
    
    this.tracks.value.push(track)
    return track
  }
  
  /**
   * 添加轨道
   */
  public addTrack(type: TrackType, name: string, targetId?: string): Track {
    const track: Track = {
      id: `track_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      name,
      type,
      targetId,
      visible: true,
      locked: false,
      height: 40,
      color: this.generateTrackColor()
    }
    
    this.tracks.value.push(track)
    return track
  }
  
  /**
   * 移除轨道
   */
  public removeTrack(trackId: string): boolean {
    const index = this.tracks.value.findIndex(t => t.id === trackId)
    if (index >= 0) {
      this.tracks.value.splice(index, 1)
      return true
    }
    return false
  }
  
  /**
   * 获取轨道
   */
  public getTrack(trackId: string): Track | undefined {
    return this.tracks.value.find(t => t.id === trackId)
  }
  
  /**
   * 添加标记
   */
  public addMarker(frame: number, name: string, color: string = '#ff0000'): Marker {
    const marker: Marker = {
      id: `marker_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
      frame,
      name,
      color
    }
    
    this.markers.value.push(marker)
    this.markers.value.sort((a, b) => a.frame - b.frame)
    
    return marker
  }
  
  /**
   * 移除标记
   */
  public removeMarker(markerId: string): boolean {
    const index = this.markers.value.findIndex(m => m.id === markerId)
    if (index >= 0) {
      this.markers.value.splice(index, 1)
      return true
    }
    return false
  }
  
  /**
   * 设置播放头位置
   */
  public setPlayhead(frame: number): void {
    this.playhead.value = Math.max(0, Math.min(frame, this.config.totalFrames - 1))
  }
  
  /**
   * 移动播放头
   */
  public movePlayhead(deltaFrames: number): void {
    this.setPlayhead(this.playhead.value + deltaFrames)
  }
  
  /**
   * 跳转到下一个标记
   */
  public goToNextMarker(): void {
    const nextMarker = this.markers.value.find(m => m.frame > this.playhead.value)
    if (nextMarker) {
      this.setPlayhead(nextMarker.frame)
    }
  }
  
  /**
   * 跳转到上一个标记
   */
  public goToPreviousMarker(): void {
    const prevMarkers = this.markers.value.filter(m => m.frame < this.playhead.value)
    if (prevMarkers.length > 0) {
      const prevMarker = prevMarkers[prevMarkers.length - 1]
      this.setPlayhead(prevMarker.frame)
    }
  }
  
  /**
   * 设置选区
   */
  public setSelection(startFrame: number, endFrame: number, tracks: string[] = []): void {
    this.selection.value = {
      startFrame: Math.min(startFrame, endFrame),
      endFrame: Math.max(startFrame, endFrame),
      tracks
    }
  }
  
  /**
   * 清除选区
   */
  public clearSelection(): void {
    this.selection.value = null
  }
  
  /**
   * 设置缩放级别
   */
  public setZoom(zoom: number): void {
    this.zoom.value = Math.max(0.1, Math.min(zoom, 10))
    this.config.pixelsPerFrame = 4 * this.zoom.value
  }
  
  /**
   * 缩放到适合
   */
  public zoomToFit(containerWidth: number): void {
    const requiredPixelsPerFrame = containerWidth / this.config.totalFrames
    const newZoom = requiredPixelsPerFrame / 4
    this.setZoom(newZoom)
  }
  
  /**
   * 滚动到播放头
   */
  public scrollToPlayhead(containerWidth: number): void {
    const playheadX = this.playhead.value * this.config.pixelsPerFrame
    const centerX = containerWidth / 2
    
    this.scrollX.value = Math.max(0, playheadX - centerX)
  }
  
  /**
   * 将像素位置转换为帧
   */
  public pixelToFrame(pixel: number): number {
    return Math.round((pixel + this.scrollX.value) / this.config.pixelsPerFrame)
  }
  
  /**
   * 将帧转换为像素位置
   */
  public frameToPixel(frame: number): number {
    return frame * this.config.pixelsPerFrame - this.scrollX.value
  }
  
  /**
   * 对齐到帧
   */
  public snapToFrame(frame: number): number {
    if (!this.config.snapToFrames) return frame
    return Math.round(frame)
  }
  
  /**
   * 生成轨道颜色
   */
  private generateTrackColor(): string {
    const colors = [
      '#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FFEAA7',
      '#DDA0DD', '#98D8C8', '#F7DC6F', '#BB8FCE', '#85C1E9'
    ]
    return colors[this.tracks.value.length % colors.length]
  }
  
  /**
   * 导出时间轴数据
   */
  public export(): any {
    return {
      id: this.id,
      name: this.name.value,
      config: { ...this.config },
      playhead: this.playhead.value,
      tracks: this.tracks.value.map(t => ({ ...t })),
      markers: this.markers.value.map(m => ({ ...m })),
      selection: this.selection.value ? { ...this.selection.value } : null,
      zoom: this.zoom.value,
      scrollX: this.scrollX.value,
      scrollY: this.scrollY.value
    }
  }
  
  /**
   * 从数据导入时间轴
   */
  public import(data: any): void {
    this.name.value = data.name || this.name.value
    
    if (data.config) {
      Object.assign(this.config, data.config)
    }
    
    this.playhead.value = data.playhead || 0
    this.tracks.value = data.tracks || []
    this.markers.value = data.markers || []
    this.selection.value = data.selection || null
    this.zoom.value = data.zoom || 1
    this.scrollX.value = data.scrollX || 0
    this.scrollY.value = data.scrollY || 0
  }
  
  /**
   * 计算属性：时间轴总宽度
   */
  public get totalWidth() {
    return computed(() => this.config.totalFrames * this.config.pixelsPerFrame)
  }
  
  /**
   * 计算属性：时间轴总高度
   */
  public get totalHeight() {
    return computed(() => this.tracks.value.reduce((sum, track) => sum + track.height, 0))
  }
  
  /**
   * 计算属性：当前时间（秒）
   */
  public get currentTimeInSeconds() {
    return computed(() => this.playhead.value / this.config.fps)
  }
  
  /**
   * 计算属性：总时长（秒）
   */
  public get totalDurationInSeconds() {
    return computed(() => this.config.totalFrames / this.config.fps)
  }
}
